package ncov.dao.impl;

import ncov.dao.StudentDao;
import ncov.listener.StudentListener;
import ncov.model.PageModel;
import ncov.model.Student;
import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.io.Serializable;
import java.util.List;

/**
 * @author WuChangJian
 * @date 2020/5/28 10:36
 */
@Repository
public class StudentDaoImpl implements StudentDao {

    private Logger logger = Logger.getLogger(StudentDaoImpl.class);
    @Autowired
    private SessionFactory sessionFactory;

    private Session getSession() {
        return sessionFactory.getCurrentSession();
    }

    @Override
    public Student queryById(String id) {
        Session session = getSession();
        Query query = session.createQuery("FROM Student where stuId=?");
        query.setParameter(0, id);
        Student student = (Student) query.uniqueResult();
        return student;
    }

    @Override
    public Student queryById(Integer id) {
        return getSession().get(Student.class, id);
    }

    @Override
    public List<Student> queryAllByLimit(PageModel pageModel) {
        Session session = getSession();
        Criteria criteria = session.createCriteria(Student.class);
        if (pageModel.getCurrentGradeId() != null)
            criteria.add(Restrictions.eq("gradeId", pageModel.getCurrentGradeId()));
        if (pageModel.getSubmitted() == -1) {

        } else if(pageModel.getSubmitted() == 0) {
            criteria.add(Restrictions.isNotNull("reportRecord"));
        } else {
            criteria.add(Restrictions.isNull("reportRecord"));
        }
        if (pageModel.getSearchKey() != null) {
            // 多字段模糊查询
            criteria.add(Restrictions.or(Restrictions.like("stuId", pageModel.getSearchKey(), MatchMode.ANYWHERE),
                    Restrictions.like("name", pageModel.getSearchKey(), MatchMode.ANYWHERE)));
        }
        criteria.setFirstResult(pageModel.getCurrentPage());
        criteria.setMaxResults(pageModel.getCount());
        criteria.addOrder(Order.asc("stuId"));
        return criteria.list();
    }

    @Override
    public List<Student> queryAll(Student student) {
        Session session = getSession();
        String sql = "FROM Student where 1=1 ";
        if (student.getGradeId() != null) {
            sql = sql + "and gradeId=" + student.getGradeId();
        }
        Query query = session.createQuery(sql);
        return query.list();
    }

    public List<Student> queryReportIsNotNull(int gradeId) {
        Session session = getSession();
        Criteria criteria = session.createCriteria(Student.class);
        criteria.add(Restrictions.eq("gradeId", gradeId));
        criteria.add(Restrictions.isNotNull("reportRecord"));
        criteria.addOrder(Order.asc("stuId"));
        return criteria.list();
    }

    @Override
    public int insert(Student student) {
        Session session = getSession();
        Serializable save = session.save(student);
        logger.info("新增学生记录主键为-->"+save);
        return 0;
    }


    /**
     * 批量新增
     * @param students 学生集合
     *  注：由于hibernate存在session缓存保存刚刚操作过的实例对象，若批量插入，有可能导致OOM
     *          所以我们需要定期flush和clear，将所有缓存写入并清空.该方法写入几个实例
     *          会有外部@StudentListener监听器中的save方法所控制
     * @see StudentListener#saveData(ncov.model.Staff)
     */
    @Override
    public void batchInsert(List<Student> students) {
        Session session = getSession();
        for (Student student : students) {
            session.save(student);
        }
        session.flush();
        session.clear();
    }


    @Override
    public int update(Student student) {
        Session session = getSession();
        session.update(student);
        return 0;
    }

    @Override
    public int deleteById(Integer id) {
        Student student = getSession().get(Student.class, id);
        getSession().delete(student);
        return 0;
    }
}
